package com.iqiyi.pps.epg.core.utils;

import com.iqiyi.pps.epg.core.dao.base.Page;
import com.iqiyi.pps.epg.core.dao.base.PropertyFilter;
import org.apache.commons.lang.StringUtils;

import java.util.List;

/**
 * Created by lemuel on 2015/11/19.
 */
public final class SqlUtil {

    public static String buildQueryStringByPropertyFilter(final Page<?> page, String hql, final List<PropertyFilter> filters) {
        return buildAppendPage(page, buildWithPropertyFilter(hql,filters ) );
    }

    public static String buildWithPropertyFilter(String hql,final List<PropertyFilter> filters){
        StringBuilder sb = new StringBuilder(hql);

        if (StringUtils.indexOfIgnoreCase(hql, "where") > 0) {
            sb.append(" and 1=1 ");
        } else {
            sb.append(" where 1=1 ");
        }

        for (PropertyFilter filter : filters) {
            if (!filter.hasMultiProperties()) { //只有一个属性需要比较的情况.
                sb.append(" and ");
                sb.append(filter.getPropertyName());
                sb.append(" ");
                sb.append(getSQLOperatorByFilterMatchType(filter.getMatchType()));
                sb.append(" '");
                if (filter.getMatchType() == PropertyFilter.MatchType.LIKE) {
                    sb.append("%" + filter.getMatchValue() + "%");
                } else {
                    sb.append(filter.getMatchValue());
                }
                sb.append("' ");
            } else {//包含多个属性需要比较的情况,进行or处理.
                sb.append(" and ( ");

                int i = 0;
                for (String param : filter.getPropertyNames()) {
                    if (i > 0) sb.append(" or ");
                    sb.append(param);
                    sb.append(" ");
                    sb.append(getSQLOperatorByFilterMatchType(filter.getMatchType()));
                    sb.append(" '");
                    if (filter.getMatchType() == PropertyFilter.MatchType.LIKE) {
                        sb.append("%" + filter.getMatchValue() + "%");
                    } else {
                        sb.append(filter.getMatchValue());
                    }
                    sb.append("' ");
                    i++;
                }
                sb.append(" ) ");
            }
        }
        return sb.toString();
    }

    public static String buildAppendPage(final Page<?> page, String hql) {
        StringBuilder sb = new StringBuilder();
        //构造排序参数
        if (page != null && page.isOrderBySetted()) {
            String[] orderByArray = StringUtils.split(page.getOrderBy(), ',');
            String[] orderArray = StringUtils.split(page.getOrder(), ',');

            for (int i = 0; i < orderByArray.length; i++) {
                if (i == 0) {
                    sb.append(" order by ");
                } else {
                    sb.append(",");
                }

                sb.append(orderByArray[i]);
                sb.append(" ");
                if (Page.ASC.equals(orderArray[i])) {
                    sb.append(Page.ASC);
                } else {
                    sb.append(Page.DESC);
                }
            }
        }
        return hql +  sb.toString();
    }

    public static String buildAppendPageLimit(final Page<?> dbPage, String hql) {
       return  hql + " LIMIT " + (dbPage.getPageNo() - 1) * dbPage.getPageSize() + " , " + dbPage.getPageSize();
    }

    private static String getSQLOperatorByFilterMatchType(PropertyFilter.MatchType matchType) {
        String operator = "";
        //根据MatchType构造criterion
        switch (matchType) {
            case EQ:
                operator = "=";
                break;
            case NEQ:
                operator = "!=";
                break;
            case LIKE:
                operator = "like";
                break;

            case LE:
                operator = "<=";
                break;
            case LT:
                operator = "<";
                break;
            case GE:
                operator = ">=";
                break;
            case GT:
                operator = ">";
        }
        return operator;
    }
}
